/* 
 * cms，一个基于J2EE架构内容管理系统
 * Copyright © GrayRabbit Co., Ltd. All rights reserved.
 * Department:运营department
 * 更多信息请访问：
 * http://code.google.com/p/gray-rabbit-cms/
 */
package org.grayrabbit.cms.service.site.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.grayrabbit.cms.constant.ConstantOperCode;
import org.grayrabbit.cms.constant.DBInitId;
import org.grayrabbit.cms.constant.DictionaryStaticValues;
import org.grayrabbit.cms.dao.category.CategoryDao;
import org.grayrabbit.cms.dao.content.ContentDao;
import org.grayrabbit.cms.dao.plugins.SurveyDao;
import org.grayrabbit.cms.dao.site.SiteDao;
import org.grayrabbit.cms.dao.topic.TopicDao;
import org.grayrabbit.cms.entity.Category;
import org.grayrabbit.cms.entity.OperLog;
import org.grayrabbit.cms.entity.Site;
import org.grayrabbit.cms.entity.Topic;
import org.grayrabbit.cms.service.category.impl.CategoryCache;
import org.grayrabbit.cms.service.category.impl.CategoryServiceImpl;
import org.grayrabbit.cms.service.site.SiteService;
import org.grayrabbit.cms.util.FilePathSptUtil;
import org.grayrabbit.cms.vo.category.CategoryBean;
import org.grayrabbit.cms.vo.content.ContentBean;
import org.grayrabbit.cms.vo.plugins.SurveyBean;
import org.grayrabbit.cms.vo.site.SiteBean;
import org.grayrabbit.cms.vo.topic.TopicBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.grayrabbit.dao.util.Page;
import org.grayrabbit.service.impl.GenericServiceImpl;
/**
 * <b>OperLog</b>的service实现类，事务加此处：





 * @version 1.0,创建时间: 2011-05-16 15:11:17  
 */
@Service
@Transactional
public class SiteServiceImpl extends GenericServiceImpl implements SiteService {
	private static final Logger logger = LoggerFactory.getLogger(CategoryServiceImpl.class);
	
	/**
	 * 注入dao层：
	 */
	@Autowired
	@Qualifier("siteDaoImpl")
	private SiteDao siteDao;
	
	@Autowired
	@Qualifier("categoryDaoImpl")
	private CategoryDao categoryDao;
	
	@Autowired
	@Qualifier("topicDaoImpl")
	private TopicDao topicDao;
	
	@Autowired
	@Qualifier("contentDaoImpl")
	private ContentDao contentDao;
	
	@Autowired
	@Qualifier("surveyDaoImpl")
	private SurveyDao surveyDao;
	
	
	/**
	 * 此方法执行时为只读事务：
	 * @see SiteService#getOperLog(String)
	 */
	@Transactional(readOnly=true)
	public Site getSite(final String siteId){
		Site site = siteDao.findById(siteId);
		siteDao.initialize(site);
		//siteDao.initialize(site.getCategories());
		return site;
	}
	
	
	@Transactional(readOnly=true)
	public Site getSiteWithAllCategory(final String siteId){
		Site site = null;
	/*	boolean falg = (boolean)CategoryContext.getSiteFlag(siteId);
		if(falg){
			site = CategoryContext.getSite(siteId);			
		}else {
			site = initSiteAndCat(siteId);
			CategoryContext.addSiteMap(siteId,site);
			CategoryContext.addSiteFlag(siteId, true);
		}*/
		return site;
	}
	
	
	/**  当前站点的所有栏目结合
	 * @param siteId
	 * @return
	 */
	Object lock = new Object();
	private List<Category> allCurrentSiteCategories(final String siteId){
		boolean flag = (boolean)CategoryCache.getSiteCategoriesFlag(siteId); 
		if(flag){
			return  CategoryCache.getSiteCategories(siteId);			
		}	 
		synchronized (lock) {
			boolean flags = (boolean)CategoryCache.getSiteCategoriesFlag(siteId);
			if(flags){
				return  CategoryCache.getSiteCategories(siteId);	
			}				
		 
			List<Category> list =categoryDao.findBySiteId(siteId);
			for(Category c: list){
				categoryDao.initialize(c.getCategory());
			} 
			CategoryCache.addSiteCategoriesMap(siteId,list);
			CategoryCache.addSiteCategoriesFlag(siteId, true); 
			return list;
		}
	}
	/**过滤权限的栏目集合
	 * @param set  当前管理员的权限集合
	 * @param currentSiteId 当前站点
	 * @param type  true：category，false：content
	 * @return
	 */
	Object locked = new Object();
	public String hasAuthCodeCategories(Set<String> authSet,
			String currentSiteId, String adminId, boolean type,
			String siteName, String contentPath,boolean needUrl) {
		try {
			if (StringUtils.isBlank(currentSiteId)
					|| StringUtils.isBlank(adminId)
					|| StringUtils.isBlank(siteName))
				throw new IllegalArgumentException(
						"currentSiteId or adminId or siteName can not be blank !");
			
			if(DBInitId.CMS_SUPPER_ADMIN_ID.equals(adminId)){
				List<Category> list = allCurrentSiteCategories(currentSiteId);
				return supperAdminJsonInfos(list, siteName, type, contentPath, needUrl);
			}
			
			String key =adminId+"_"+currentSiteId;
			 
			List<Category> cats = allCurrentSiteCategories(currentSiteId);// 全部栏目
			boolean flag = CategoryCache.getAuthCategoriesFlag(key);
			if(flag){				 
				return loadCategoriesJSON(key,siteName,contentPath,needUrl,type);
			}			
			synchronized (locked) {
				boolean flags = CategoryCache.getAuthCategoriesFlag(key);
				if(flags){
					return loadCategoriesJSON(key,siteName,contentPath,needUrl,type);
				}
				cacheCAtegories(key, cats, authSet);
				return loadCategoriesJSON(key,siteName,contentPath,needUrl,type);
			}
 
		} catch (Exception e) {
			logger.error("栏目树加载异常", e);
			return "{ id:0,name:'栏目树加载异常'}";
		}
	}
	
	/**缓存*/
	private void cacheCAtegories(String key, List<Category> catList,
			Set<String> authSet) {		
		List<Category> hasAuth_cat = authFiltrateCategories(catList, true,authSet);// 拥有栏目权限的栏目集合
		List<Category> fathers_cat = authFatherCategories(hasAuth_cat,catList); // 无栏目权限的父级栏目集合
		List<Category> hasAuth_con = authFiltrateCategories(catList, false,authSet);// 拥有内容权限的栏目集合
		List<Category> fathers_con = authFatherCategories(hasAuth_con,catList); //  无内容权限的父级栏目集合
		CategoryCache.addAuthCategories_cat(key, hasAuth_cat);
		CategoryCache.addAuthNoCats_cat(key, fathers_cat);
		CategoryCache.addAuthCategories_content(key, hasAuth_con);
		CategoryCache.addAuthNoCats_content(key, fathers_con);
		CategoryCache.addAuthCategoriesFlag(key, new Boolean(true)); 
	} 
	
	private String loadCategoriesJSON(String key
			, String siteName, String contentPath,
			boolean needUrl, boolean type) {
		List<Category> hasAuth = null;
		List<Category> fathers = null;
		if(type){
			hasAuth = CategoryCache.getAuthCategories_cat(key);
			fathers = CategoryCache.getAuthNoCats_cat(key);	
		}else{
			hasAuth = CategoryCache.getAuthCategories_content(key);
			fathers = CategoryCache.getAuthNoCats_content(key);	
		}	
		
		if(hasAuth.isEmpty()){
			if(needUrl){
				String link = null;
				if(type){
					link = "/category/category-list.action";
				}else{
					link = "/content/content-site.action";
				}
				return "{id:'0',name:'"+siteName+"',nocheck:true,target:'mainframe',url:'"
							+contentPath+link+"'}";			 
			}else{				
				return "{id:'0',name:'"+siteName+"',nocheck:true}";
			}			 
		}
		StringBuffer sb = new StringBuffer();
		String url = loadSb(sb, contentPath, siteName, needUrl, type);
		
		loadJSONInfos(sb, hasAuth, needUrl, contentPath, url,false);//有权限的集合
		 
		loadJSONInfos(sb, fathers, needUrl, contentPath, url,true);//无权限的集合  needUrl false
		 
		String json = sb.toString();
		if(json.endsWith(",")){
			json = json.substring(0, json.length()-1);
		} 
		json += "]";
		return json;
	}
	
	private String loadSb(StringBuffer sb ,String path,String siteName,boolean needUrl,boolean type){
		sb.append("[")
		  .append("{ id:'0',name:'"+siteName+"',nocheck:true,");
		if(needUrl){
			sb.append("url:'").append(path);
			if(type){
				sb.append("/category/category-list.action',");
			}else{
				sb.append("/content/content-site.action',");
			}
			sb.append("target:'mainframe',");	
		} 
		sb.append("open:true");
		sb.append("},");
		String url = null;
		if(type){
			url = "/category/category-list.action?category.categoryId=";			
		}else{
			url = "/content/content-list.action?content.category.categoryId=";			
		}
		return url;
	}
	
	private String supperAdminJsonInfos(List<Category> list,
			String siteName, boolean type,String path, boolean needUrl) {
		StringBuffer sb = new StringBuffer();
		String url = loadSb(sb, path, siteName, needUrl, type);
		if(list.isEmpty()){
			if(needUrl ){
				String link = null;
				if(type){
					link = "/category/category-list.action";
				}else{
					link = "/content/content-site.action";
				}
				return "{id:'0',name:'"+siteName+"',nocheck:true,target:'mainframe',url:'"
							+path+link+"'}";			 
			}else{				
				return "{id:'0',name:'"+siteName+"',nocheck:true}";
			}
		}
		loadJSONInfos(sb, list, needUrl, path, url,false);
		String json = sb.toString();
		if(json.endsWith(",")){
			json = json.substring(0, json.length()-1);
		} 
		json += "]";
		return json;
	}

	/** 装载 set TO JSON
	 *  flag:是否加链接，url：链接
	 * */
	private void loadJSONInfos(StringBuffer sb, Collection<Category> set,
			boolean flag, String path, String url,boolean nocheck) {
		for(Category c : set){			 
			sb.append("{")
			  .append("id:'").append(c.getCategoryId()).append("',") 
			  .append("pId:'");
			if(c.getCategory()==null || c.getCategory().getCategoryId() == null){				
				sb.append('0');
			}else{
				sb.append(c.getCategory().getCategoryId());
			}
			sb.append("',");
			if(flag){				
				sb.append("url:'") .append(path).append(url)
				  .append(c.getCategoryId()).append("',")
				  .append("target:'mainframe',");
			}
			if(nocheck){
				sb.append("nocheck:true,");
			}
			sb.append("name:'") .append(c.getCatName()).append("'")
			  .append("},"); 
		} 
	}

	/**父级栏目集合（并且过滤掉有权限的）
	 * @param hasAuth
	 * @return
	 */
	private List<Category> authFatherCategories(List<Category> hasAuth,List<Category> list) {
		Set<Category> set = new HashSet<Category>();
		for(Category c: hasAuth){
			loadFathers(c, set);
		}
		//过滤有权限的（滤重）
		Set<Category> setClear = new HashSet<Category>();
		setClear.addAll(set);		
		for(Category no : set){
			for(Category yes : hasAuth){
				if(no.getCategoryId().equals(yes.getCategoryId())){
					setClear.remove(no);
					continue;
				}
			}
		}
		// 排序
		List<Category> listClear = new ArrayList<Category>();
		for(Category c: list){
			if(setClear.contains(c)){ 
				listClear.add(c); 
			}
		}
		
		return listClear;
	}
	
	private void loadFathers(Category c,Set<Category> set){
		if(c.getCategory()!=null){
			set.add(c.getCategory());
			loadFathers(c.getCategory(), set);
		}
	}


	/**过滤出 栏目权限
	 * @param set  当前登录用户的权限  
	 * @param type  true：category，false：content 
	 * @return
	 */
	private Set<String> loadAuth(Set<String> set,Boolean type){
		Set<String> Auth = new HashSet<String>();
		for(String s:set){
			if(type){
				if(s.startsWith(ConstantOperCode.CAT_CAT_EDIT) 
						|| s.startsWith(ConstantOperCode.CAT_CAT_GEN)){
					//TODO  栏目权限变更此处要跟随修改
					Auth.add(s);
				}				
			}else{
				if(s.startsWith(ConstantOperCode.CAT_DOC_EDIT) 
						|| s.startsWith(ConstantOperCode.CAT_DOC_AUDIT)
						|| s.startsWith(ConstantOperCode.CAT_DOC_UNLOCK)){
					//TODO  栏目内容权限变更此处要跟随修改
					Auth.add(s);
				}
			}
		}
		return Auth;
	} 
	
 
	/**过滤出 具有权限的栏目集合
	 * @param categoryList  所有栏目
	 * @param type  true：category，false：content 
	 * @param authSet  所有权限
	 * @return
	 */
	private List<Category> authFiltrateCategories(List<Category> categoryList,
			Boolean type, Set<String> authSet) {
		List<Category> authCategory = new ArrayList<Category>();
		Set<Category> set = new HashSet<Category>();
		Set<String> CatAuth = loadAuth(authSet, type);// 来过滤后的权限
		for(Category c:categoryList){
			for(String s:CatAuth){
				if(s.endsWith("-"+c.getCategoryId())){				    
					if(!set.contains(c)){
						set.add(c);
						authCategory.add(c);
					}
				}
			}
		}
		set.clear();
		return authCategory;
	}
  	
	@Transactional(readOnly=true)
	private void initializeCategory(Category cat){
		siteDao.initialize(cat);
		if(cat.getCategories()==null)
			return;
		for (Category c : cat.getCategories()) {
			initializeCategory(c);
		}
	}
	
	public Site initSiteAndCat(final String siteId){ 
		Site site = siteDao.findById(siteId);
		siteDao.initialize(site);
		for (Category cat : site.getCategories()) {
			initializeCategory(cat);
		}
		return site;
	}
	
	/**
	 * @see SiteService#delete(String)
	 */
	@Transactional
	public void delete(final Site site) {
		siteDao.makeTransient(site);
		CategoryCache.removeSiteCategoriesAndFlagInfo(site.getSiteId());
	}
	
	/**
	 * @see SiteService#save(OperLog)
	 */
	@Transactional
	public void save(final Site site) {
		siteDao.makePersistent(site);
		CategoryCache.addSiteCategoriesFlag(site.getSiteId(), false);
		CategoryCache.removeSiteCategories(site.getSiteId());
	}
	
	/**
	 * 此方法执行时为只读事务：
	 * @see SiteService#getPage(SiteBean)
	 */
	@Transactional(readOnly=true)
	public Page<Site> getPage(final SiteBean siteBean){
		Page<Site> page =  new Page<Site>();
		page.setTotal(siteDao.count(siteBean));
		page.setResult(siteDao.findByQc(siteDao.assembly(siteBean)));
		return page;
	}

	/**
	 * 此方法执行时为只读事务：
	 * @see SiteService#list(Page, SiteBean)
	 */
	public void list(Page<Site> page, SiteBean siteBean) {
		if(page==null)
			return;
		if(page.isAutoCount()){
			page.setTotal(siteDao.count(siteBean));
		}
		page.setResult(siteDao.findByPage(page,siteBean));
	}
	
	/**
	 * 根据主键id列删除，批量删除OperLog
	 * @see SiteService#delete(String[])
	 */
	public void delete(final String[] key) {
		int i =0;
		for(String id : key){
			siteDao.makeTransient(siteDao.findById(id));
			i++;
			if(i==MAX_CLEAR)
				siteDao.clear();
			CategoryCache.removeSiteCategoriesAndFlagInfo(id);
		}
		
	}
	/**
	 * 查询所有记录
	 * @return 
	 */
	public List<Site> findALL(SiteBean siteBean) {
		return siteDao.findByPage(siteBean);
	}
	
	/**
	 * 检查站点名称唯一性
	 * @param role
	 * @return
	 */
	public Boolean checkNameUnique(String siteName,String stname){
		return siteDao.checkNameUnique(siteName,stname);
	}
	/**
	 * 检查站点简称名称唯一性
	 * @param role
	 * @return
	 */
	public Boolean checkSimplenameunique(String siteShortName,String oldname){
		return siteDao.checkSimplenameunique(siteShortName,oldname);
	}
	/**  
	 *  本方法为权限分配 中站点及权限分配的所有站点栏目树所专有的方法，不允许修改。
	 *  
	 */
	@Transactional(readOnly=true)
	public List<Site> getAllSiteWithAllCategory() {
		List<Site> sites = new ArrayList<Site>();
		Site site = null;
		List<Site> list = siteDao.findAll();
		for(Site s : list){			 
				site = getSiteWithAllCategory(s.getSiteId());
				sites.add(site);			 
		} 
		return sites;
	}

	public List<Site> findAllSiteWithTopic() {
		List<Site> sites = siteDao.findAll();
		for(Site s:sites){
			siteDao.initialize(s);
			siteDao.initialize(s.getTopics());
		}
		return sites;
	}

	public List<Site> findAllUsableSite() { 
		return siteDao.findAllUsableSite();
	}
	
	
	public int countCatBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			CategoryBean categoryBean = new CategoryBean();
			Site site = new Site();
			site.setSiteId(siteId);
			categoryBean.setSite(site);
			count+=categoryDao.count(categoryBean);
		}
		return count;
	}
	public int countTopicBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			TopicBean topicBean = new TopicBean();
			Site site = new Site();
			site.setSiteId(siteId);
			topicBean.setSite(site);
			count+=topicDao.count(topicBean);
		}
		return count;
	}
	public int countContentBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			List<Category> catList = categoryDao.findBySiteId(siteId);
			for(Category ca:catList){
				ContentBean contentBean = new ContentBean();
				contentBean.setCategory(ca);
				count+=contentDao.countAllByPublish(contentBean);
			}
//			List<Topic> topicList = topicDao.findBySiteId(siteId);
//			for(Topic topic:topicList){
//				ContentBean contentBean = new ContentBean();
//				contentBean.setTopic(topic);
//				count+=contentDao.countAllByPublish(contentBean);
//			}
		}
		return count;
	}
	public int countMoreCatBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			CategoryBean categoryBean = new CategoryBean();
			Site site = new Site();
			site.setSiteId(siteId);
			categoryBean.setSite(site);
			count+=categoryDao.count(categoryBean);
		}
		return count;
	}
	public int countMoreTopicBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			TopicBean topicBean = new TopicBean();
			Site site = new Site();
			site.setSiteId(siteId);
			topicBean.setSite(site);
			count+=topicDao.count(topicBean);
		}
		return count;
	}
	public int countMoreContentBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			List<Category> catList = categoryDao.findBySiteId(siteId);
			for(Category ca:catList){
				ContentBean contentBean = new ContentBean();
				contentBean.setCategory(ca);
				if(ca.getIsAudit()!=null && !ca.getIsAudit().booleanValue()){
					contentBean.setContentStatus(DictionaryStaticValues.CONTENT_STATUS_NEW);
				}else{
					contentBean.setContentStatus(DictionaryStaticValues.CONTENT_STATUS_SUCCESS);
				}
				contentBean.setMaxPublishTime(new Date());
				count+=contentDao.count(contentBean);
			}
//			List<Topic> topicList = topicDao.findBySiteId(siteId);
//			for(Topic topic:topicList){
//				ContentBean contentBean = new ContentBean();
//				contentBean.setTopic(topic);
//				if(topic.getIsAudit()!=null && topic.getIsAudit().booleanValue()){
//					contentBean.setContentStatus(DictionaryStaticValues.CONTENT_STATUS_SUCCESS);
//				}else{
//					contentBean.setContentStatus(DictionaryStaticValues.CONTENT_STATUS_NEW);
//				}
//				count+=contentDao.countAllByPublish(contentBean);
//			}
		}
		return count;
	}
	public int countSurveyBySites(List<String> list){
		int count = 0;
		for(String siteId:list){
			SurveyBean surveyBean = new SurveyBean();
			Site site = new Site();
			site.setSiteId(siteId);
			surveyBean.setSite(site);
			count+=surveyDao.count(surveyBean);
		}
		return count;
	}
	
	public String  AllSiteCategoriesJsonForAuth(){
		List<Site>  list = siteDao.findAll();
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		sb.append("{id:'0',name:'站点栏目权限树',nocheck:true,open:true,isParent:true},");
		for(int i=0;i<list.size();i++){
			Site site = list.get(i);
			List<Category> categories = allCurrentSiteCategories(site.getSiteId());
			String id = site.getSiteId()+"_"+i;
			sb.append("{id:'")
			  .append(id)			   
			  .append("',pId:'0',name:'")
			  .append(site.getSiteName())
			  .append("',nocheck:true},");
			loadAllSiteCategoriesJson(sb, categories, id);
		}
		String json = sb.toString();
		if(json.endsWith(",")){
			json = json.substring(0, json.length()-1); 
		}		
		return 	json+"]";	
	}
	
    private StringBuffer loadAllSiteCategoriesJson(StringBuffer sb,List<Category> categories,String pId){
    	for(Category c:categories){
    		sb.append("{id:'").append(c.getCategoryId()).append("',pId:'");
    		if(c.getCategory()!=null && c.getCategory().getCategoryId()!=null){
    			sb.append(c.getCategory().getCategoryId());
    		}else{
    			sb.append(pId);
    		}
    		sb.append("',name:'").append(c.getCatName()).append("'},");    		  
    	}    	
    	return sb;
    }
    private StringBuffer loadAllSiteTopicsJson(StringBuffer sb,Set<Topic> Topics,String pId){
    	for(Topic t:Topics){
    		sb.append("{id:'")
    		  .append(t.getTopicId())
    		  .append("',pId:'")
    		  .append(pId)
    		  .append("',name:'")
    		  .append(t.getTopicName())
    		  .append("'},");    		  
    	}    	
    	return sb;
    }

//    private
    
	public String AllSiteTopicsJsonForAuth(String siteId) {
		List<Site> list = null;
		if(StringUtils.isBlank(siteId)){
			list = findAllSiteWithTopic();
		}else{			
			Site site = this.getSite(siteId);
			siteDao.initialize(site);
			siteDao.initialize(site.getTopics());
			list = new ArrayList<Site>();
			list.add(site);
		}		
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		sb.append("{id:'0',name:'站点专题权限树',nocheck:true,open:true,isParent:true},");
		for(int i=0;i<list.size();i++){
			Site site = list.get(i);			 
			String id = site.getSiteId()+"_"+i;
			sb.append("{id:'")
			  .append(id)			   
			  .append("',pId:'0',name:'")
			  .append(site.getSiteName())
			  .append("',nocheck:true},");
			loadAllSiteTopicsJson(sb, site.getTopics(), id);			
			 
		}
		String json = sb.toString();
		if(json.endsWith(",")){
			json = json.substring(0, json.length()-1); 
		}		
		return 	json+"]";	
	}


	public String findSiteInfo(String area) {
		try {
			
			SiteBean bean = new SiteBean();
			bean.setArea(area);
			bean.setSiteStatus(true);
			List<Site> list = siteDao.findByPage(bean);
			if(list.isEmpty()){				
				return "{'flag':false}";
			}else{
				Site site = list.get(0);
				list.clear();
				return "{'flag':true,'a':'"+site.getSiteDomain()+"','img':'"+FilePathSptUtil.UPLOAD_URL+site.getLogo()+"'}";
			}
		} catch (Exception e) {
			return "{'flag':false}";
		} finally{
			siteDao.clear();
		}
	}
}